import ResourceManager from "../manager/ResourceManager";

const { ccclass } = cc._decorator;

export interface LoadingTask {
  readonly weight: number; // 占比权重（总和应为 1）
  readonly description: string; // 描述文本
  readonly boundleName: string; // 包名
}

@ccclass
export class LoadingSystem {
  private static _instance: LoadingSystem;

  public static get instance(): LoadingSystem {
    return this._instance || (this._instance = new LoadingSystem());
  }

  private constructor() {}

  /**
   * 执行一组加载任务，并返回平滑递增的进度
   * @param tasks 任务列表
   * @param progressCallback 回调更新进度
   */
  public async runSequence(
    tasks: LoadingTask[],
    progressCallback?: (progress: number, desc: string) => void
  ): Promise<void> {
    //当前进度
    let currentProgress = 0;
    //总权重
    const totalWeight = tasks.reduce((sum, task) => sum + task.weight, 0);

    for (const task of tasks) {
      //当前任务进度比例
      const targetWeight = task.weight / totalWeight;
      //当前任务加载完成时的进度
      const targetProgress = currentProgress + targetWeight;

      // 平滑过渡到目标进度
      await this.smoothProgress(
        currentProgress,
        targetProgress,
        task.description,
        progressCallback
      );
      // 执行实际加载操作
      try {
        await ResourceManager.getInstance().loadBundleAsync(task.boundleName);
      } catch (e) {
        console.error(`[LoadingSystem] 加载失败: ${task.description}`, e);
        throw e;
      }

      //更新当前进度
      currentProgress = targetProgress;
    }

    // 确保最终进度为 1.0（故意将预设的权重总和 < 1），留给界面跳转的缓冲时间
    if (currentProgress < 1.0) {
      await this.smoothProgress(
        currentProgress,
        1.0,
        "加载完成",
        progressCallback
      );
    }
  }

  /**
   * 平滑递增进度
   */
  private async smoothProgress(
    from: number,
    to: number,
    desc: string,
    callback?: (progress: number, desc: string) => void
  ): Promise<void> {
    const step = 0.01; // 每步增加 1%
    const delayMs = 20; // 每步延迟时间（ms）

    while (from + step < to) {
      from += step;
      callback?.(from, desc);
      await new Promise((resolve) => setTimeout(resolve, delayMs));
    }

    callback?.(to, desc);
    await new Promise((resolve) => setTimeout(resolve, 50)); // 短暂暂停
  }
}
